#include <ConnectionBroker/server/TcpServer.h>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>

using namespace ConnectionBroker;
using boost::asio::ip::tcp;

TcpServer::TcpServer(const ConnectionBroker::ServerSettings& settings, 
                     boost::shared_ptr<boost::asio::ssl::context> pContext,
                     serverCallback pDefaultCallback, 
                     serverCallback pDefaultClientConnectCallback,
                     serverCallback pDefaultClientDisconnectCallback
                    ) 
: Server(settings, 
         pDefaultCallback, 
         pDefaultClientConnectCallback, 
         pDefaultClientDisconnectCallback), 
         mIoService(),
         mAcceptor(mIoService, tcp::endpoint(tcp::v4(), settings.port())),
         mContext(pContext)
{
}

TcpServer::~TcpServer()
{
}

void TcpServer::start()
{
   startAcceptingClients();
   mIoService.run();
}

void TcpServer::handleAccept(TcpClientConnectionPtr pNextClient, const boost::system::error_code& error)
{
   if(!error)
      pNextClient->start();

   startAcceptingClients();
}

void TcpServer::startAcceptingClients()
{
   TcpClientConnectionPtr pNextClient(new TcpClientConnection(mIoService, this, mContext));
   if(pNextClient->usingSsl())
   {
      mAcceptor.async_accept(pNextClient->sslSocket(), boost::bind(&TcpServer::handleAccept, this, pNextClient, boost::asio::placeholders::error));
   }
   else
   {
      mAcceptor.async_accept(pNextClient->socket(), boost::bind(&TcpServer::handleAccept, this, pNextClient, boost::asio::placeholders::error));
   }
}

